fileserver: reduce allocations in calculateEtag#7852
Open
jvoisin wants to merge 1 commit into
Open
Conversation
calculateEtag runs for every static file served (and on conditional If-None-Match revalidations). It used a non-presized strings.Builder plus two strconv.FormatInt calls, each allocating an intermediate string and triggering builder growth, which is about six allocations per call. This commit builds the quoted etag into a fixed 32-byte stack array with strconv.AppendInt instead, so only the final string is heap-allocated. The output format is byte-for-byte identical. Two base-36 int64 values plus the two quote bytes are at most 30 bytes (the worst case is MinInt64, which is `1y2p0ij32e8e8`, so 13 digits plus a minus sign, so two times 14, plus the quotes, for a total of 30 characters), so the buffer never spills. And even if it did, which it doesn't append would simply grow it onto the heap without changing the result. Adds a benchmark, as required by the policy: CalculateEtag: - sec/op 347.6n -> 186.2n (-46.42%) - B/op 112 -> 56 (-50%) - allocs/op 6 -> 2 (-66.67%) It removes some CPU work, but more interestingly four of six per-file allocations on a hot path of a very common handler, lowering per-request garbage and GC pressure.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
calculateEtag runs for every static file served (and on conditional If-None-Match revalidations). It used a non-presized strings.Builder plus two strconv.FormatInt calls, each allocating an intermediate string and triggering builder growth, which is about six allocations per call.
This commit builds the quoted etag into a fixed 32-byte stack array with strconv.AppendInt instead, so only the final string is heap-allocated. The output format is byte-for-byte identical. Two base-36 int64 values plus the two quote bytes are at most 30 bytes (the worst case is MinInt64, which is
1y2p0ij32e8e8, so 13 digits plus a minus sign, so two times 14, plus the quotes, for a total of 30 characters), so the buffer never spills. And even if it did, which it doesn't append would simply grow it onto the heap without changing the result.Adds a benchmark, as required by the policy:
CalculateEtag:
It removes some CPU work, but more interestingly four of six per-file allocations on a hot path of a very common handler, lowering per-request garbage and GC pressure.
Assistance Disclosure
"No AI was used."